#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
JSON格式BIN文件发送器

该模块提供以下功能:
1. 将BIN文件数据按4字节分块
2. 生成符合指定JSON格式的数据包
3. 计算CRC8校验值
4. 处理地址和索引字段
"""

import json
from typing import Dict, List, Optional, Tuple


class JSONBinSender:
    """JSON格式BIN文件发送器类"""
    
    def __init__(self, bin_data: bytes, start_address: int = 0x08000000, block_length: int = 256, chip_type: str = "ch32v10x"):
        """
        初始化JSON BIN发送器
        
        Args:
            bin_data (bytes): BIN文件数据
            start_address (int): 起始地址，默认为0x08000000
            block_length (int): 每个块的长度，默认为256字节
        """
        self.bin_data = bin_data
        self.start_address = start_address
        self.block_length = block_length
        self.current_index = 0
        self.current_addr = start_address
        self.sent_bytes = 0
        self.index_in_block = 0
        self.chip_type = chip_type

    def get_next_packet(self) -> Optional[Dict]:
        if self.current_index >= len(self.bin_data):
            return None

        chunk = self.bin_data[self.current_index:self.current_index + 8]
        fill_value = 0xFFFF if self.chip_type == "ch32v10x" else 0xE339
        # 补齐到8字节
        while len(chunk) < 8:
            if self.chip_type == "ch32v10x":
                chunk += b'\xFF'
            else:  # ch32v30x
                if len(chunk) % 2 == 0 and len(chunk) < 7:
                    chunk += b'\xE3\x39'
                else:
                    chunk += b'\x39'

        chunk = chunk[:8]  # 防止超出8字节

        data1 = (chunk[0] << 8) | chunk[1]
        data2 = (chunk[2] << 8) | chunk[3]
        data3 = (chunk[4] << 8) | chunk[5]
        data4 = (chunk[6] << 8) | chunk[7]
        crc = self._calculate_crc8(data1, data2, data3, data4)

        is_last_packet = (self.current_index + 8) >= len(self.bin_data)
        if is_last_packet:
            script = 2
        elif self.index_in_block + 8 >= self.block_length:
            script = 2
        else:
            script = 1

        packet = {
            "cmd": 996,
            "script": script,
            "addr": self.current_addr,
            "index": self.index_in_block,
            "data1": data1,
            "data2": data2,
            "data3": data3,
            "data4": data4,
            "crc": crc
        }

        self.current_index += 8
        self.sent_bytes += 8
        self.index_in_block += 8

        if self.index_in_block > (self.block_length - 8):
            self.current_addr += self.block_length
            self.index_in_block = 0

        return packet

    def _calculate_crc8(self, data1: int, data2: int, data3: int, data4: int) -> int:
        """
        计算CRC8校验值（基于4个16位数据）
        """
        crc = 0
        data = [
            (data1 >> 8) & 0xFF, data1 & 0xFF,
            (data2 >> 8) & 0xFF, data2 & 0xFF,
            (data3 >> 8) & 0xFF, data3 & 0xFF,
            (data4 >> 8) & 0xFF, data4 & 0xFF,
        ]
        for byte in data:
            crc ^= byte
            for _ in range(8):
                if crc & 0x80:
                    crc = (crc << 1) ^ 0x07
                else:
                    crc <<= 1
                crc &= 0xFF
        return crc
    
    def get_all_packets(self) -> List[Dict]:
        """
        获取所有数据包
        
        Returns:
            List[Dict]: 所有JSON格式的数据包列表
        """
        packets = []
        while True:
            packet = self.get_next_packet()
            if packet is None:
                break
            packets.append(packet)
        return packets
    
    def reset(self):
        """重置发送器状态"""
        self.current_index = 0
        self.current_addr = self.start_address
        self.sent_bytes = 0
        self.index_in_block = 0


class JSONBinReceiver:
    """JSON格式BIN文件接收器类"""
    
    def __init__(self):
        """初始化JSON BIN接收器"""
        pass
    
    def parse_response(self, response_json: str) -> Tuple[bool, Dict]:
        """
        解析回包
        
        Args:
            response_json (str): JSON格式的回包字符串
            
        Returns:
            Tuple[bool, Dict]: (是否解析成功, 解析结果字典)
        """
        try:
            response = json.loads(response_json)
            
            # 检查必需字段
            required_fields = ["cmd", "script", "result"]
            for field in required_fields:
                if field not in response:
                    return False, {"error": f"缺少必需字段: {field}"}
            
            # 严格检查cmd字段必须为996
            if int(response.get("cmd", 0)) != 996:
                return False, {"error": f"只接受cmd996指令，收到: {response.get('cmd')}"}
            
            # 检查result字段
            result = response["result"]
            if result not in [0, 1, 2]:
                return False, {"error": f"result字段值无效: {result}"}
            
            # 检查script字段
            script = response.get("script", 0)
            if script not in [1, 2, 3, 9]:
                return False, {"error": f"script字段值无效: {script}"}
            
            return True, response
            
        except json.JSONDecodeError as e:
            return False, {"error": f"JSON解析错误: {str(e)}"}
        except Exception as e:
            return False, {"error": f"解析回包时发生错误: {str(e)}"}
    
    def is_success_response(self, response_json: str) -> bool:
        """
        检查回包是否表示成功
        
        Args:
            response_json (str): JSON格式的回包字符串
            
        Returns:
            bool: 成功返回True，否则返回False
        """
        success, response = self.parse_response(response_json)
        if not success:
            return False
        
        result = response.get("result", 0)
        script = response.get("script", 0)
        # result字段: 1表示通过，2表示完成，0表示错误
        # script字段: 1表示中间包，2表示结束包
        return result in [1, 2] and script in [1, 2, 3, 9]


# 使用示例和测试函数
def main():
    """主函数，用于测试和演示"""
    print("JSON格式BIN文件发送器演示")
    # 创建测试数据 (64字节)
    test_data = bytes(range(64))
    # 创建发送器实例
    sender = JSONBinSender(test_data, 0x08000000)
    # 获取所有数据包
    packets = sender.get_all_packets()
    print(f"总共生成 {len(packets)} 个数据包")
    # 显示前几个数据包
    for i, packet in enumerate(packets[:5]):
        print(f"数据包 {i+1}: {json.dumps(packet, indent=2)}")
    # 演示接收器
    receiver = JSONBinReceiver()
    # 测试成功回包
    success_response = '{"cmd": 996, "script": 1, "result": 1}'
    success, result = receiver.parse_response(success_response)
    print(f"\n成功回包解析: {success}, 结果: {result}")
    # 测试失败回包
    fail_response = '{"cmd": 996, "script": 1, "result": 0}'
    success, result = receiver.parse_response(fail_response)
    print(f"失败回包解析: {success}, 结果: {result}")
    # 测试错误回包
    error_response = '{"cmd": 996, "script": 1}'  # 缺少result字段
    success, result = receiver.parse_response(error_response)
    print(f"错误回包解析: {success}, 结果: {result}")

if __name__ == "__main__":
    main()
